package com.wangyf.thread.c_022_question;

import java.util.ArrayList;
import java.util.List;

/**
 * 写一个固定容量同步容器:，拥有put get getCount 方法，能够支持两个生产者 10个消费者线程阻塞调用。
 * @author wangyf
 * @date 2021/1/21 21:58
 * 因为没有sleep等操作 所以经常可能 消费完才会进行生产或者 生产完10个才进行消费 需要多试验几次 或者 用 Thread.yield()
 */
public class T01_waitnotifyall {
    static ArrayList<Object> list = new ArrayList<>();
    static final int MAX = 10;
    private int size = 0;

    public synchronized void put(Object o) {
        while (size == MAX) {// 这里需要注意用while 不用if  因为下面notifyAll 可能是生产者唤醒 这时候就是满的 还要重新判断
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(o);
        size++;
        System.out.println("["+Thread.currentThread().getName()+"]生产第"+size+"个");
        this.notifyAll();
        // Thread.yield(); 看效果时 比较好
    }
    public synchronized void get() {
        while (size == 0) {// 这里需要注意用while 不用if  因为下面notifyAll 可能是消费者唤醒 这时候就是空的 还要重新判断
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.remove(0);
        size--;
        System.out.println("["+Thread.currentThread().getName()+"]获得第0个，剩余"+size+"个");
        this.notifyAll();
        // Thread.yield(); 看效果时 比较好
    }

    public static void main(String[] args) {
        T01_waitnotifyall t = new T01_waitnotifyall();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 5; j++) {
                    t.get();
                }
            }, "customer"+i).start();
        }
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                for (int j = 0; j < 25; j++) {
                    t.put(new Object());
                }
            }, "producer"+i).start();
        }
    }
}
